import time, datetime
from timeit import timeit

import pysnowball as ball
import pandas as pd
from pysnowball import cons
from pysnowball import api_ref
from pysnowball import utls

from core.dataClasses import StockTradeDataColumnName
from core.enums import Period, DateFormat
from config.config import config
from core import logger

ball.set_token(f"xq_a_token={config.get('xueqiu', 'token')};")

runtimes = {
    "kline": None,
    "realtimeQuote": None,
    "quoteList": None,
}

klineDelta = datetime.timedelta(seconds=3)
realtimeQuoteDelta = datetime.timedelta(seconds=3)
delta8hours = datetime.timedelta(hours=8)

# @timeit(number=10)
def convertDatetime(df, column:str):
    df[StockTradeDataColumnName.DATE_INDEX.value] = pd.to_datetime(df[column], unit="ms", utc=True).dt.tz_convert(
        'Asia/Shanghai')
    dateTimeStr = df[StockTradeDataColumnName.DATE_INDEX.value].dt.strftime(DateFormat.YmdHMS.value)
    df[StockTradeDataColumnName.TRADE_DATE.value] = dateTimeStr.apply(lambda x: int(x))
    df[StockTradeDataColumnName.DATE_INDEX.value] = pd.to_datetime(dateTimeStr, format=DateFormat.YmdHMS.value)
    return df

def kline(symbol: str, period : Period = Period.day, days=100) -> pd.DataFrame:
    if runtimes["kline"] is None:
        runtimes["kline"] = datetime.datetime.now()
    elif runtimes["kline"] + klineDelta < datetime.datetime.now():
        logger.info(f"访问太过频繁，休息1秒钟")
        time.sleep(1)
    symbolList = symbol.split(".")
    code =f"{symbolList[1]}{symbolList[0]}"
    beginTime = int(time.time() * 1000 + 24 * 60 * 60 * 1000)
    url = api_ref.kline.format(code, beginTime, days)
    if period == Period.minute30:
        url = url.replace("period=day", "period=30m")
    elif period == Period.week:
        url = url.replace("period=day", "period=week")
    try:
        result = utls.fetch(url)
    except:
        result = utls.fetch(url)
    df = pd.DataFrame(result["data"]["item"], columns=result["data"]["column"])
    logger.info(f"下载股票{symbol} {period.name}周期数据：{df.shape[0]}条")
    df = df.drop([
        "volume_post",
        "amount_post",
        "pe",
        "pb",
        "ps",
        "pcf",
        "market_capital",
        "balance",
        "hold_volume_cn",
        "hold_ratio_cn",
        "net_volume_cn",
        "hold_volume_hk",
        "hold_ratio_hk",
        "net_volume_hk"
             ], axis=1)
    df[StockTradeDataColumnName.DATE_INDEX.value] = df["timestamp"].apply(lambda x: datetime.datetime.utcfromtimestamp(x/1000)+delta8hours)
    df[StockTradeDataColumnName.TRADE_DATE.value] = df[StockTradeDataColumnName.DATE_INDEX.value].apply(lambda x: int(x.strftime(DateFormat.YmdHMS.value)))
    df = df.drop("timestamp", axis=1)
    df.set_index(keys=StockTradeDataColumnName.DATE_INDEX.value, inplace=True)
    df = df.rename(columns={
        "volume": StockTradeDataColumnName.VOL.value,
        "open": StockTradeDataColumnName.OPEN.value,
        "high": StockTradeDataColumnName.HIGH.value,
        "low": StockTradeDataColumnName.LOW.value,
        "close": StockTradeDataColumnName.CLOSE.value,
        "chg": StockTradeDataColumnName.CHANGE.value,
        "percent": StockTradeDataColumnName.PCT_CHG.value,
        "turnoverrate": StockTradeDataColumnName.TURNOVER_RATE.value,
        "amount": StockTradeDataColumnName.AMOUNT.value
    })
    return df


def realtimeQuote(symbol: str) -> pd.DataFrame:
    """
    实时报价
    :param symbol:
    :return:
    """
    if runtimes["realtimeQuote"] is None:
        runtimes["realtimeQuote"] = datetime.datetime.now()
    elif runtimes["realtimeQuote"] + realtimeQuoteDelta < datetime.datetime.now():
        logger.info(f"访问太过频繁，休息1秒钟")
        time.sleep(1)
    symbolList = symbol.split(".")
    code =f"{symbolList[1]}{symbolList[0]}"
    url = api_ref.realtime_quote_detail + code
    try:
        result = utls.fetch(url)
    except:
        result = utls.fetch(url)
    df = pd.DataFrame([result["data"]["quote"]])
    logger.info(f"下载股票{symbol} 实时报价数据：{df.shape[0]}")
    df = df.loc[:, ["volume", "open", "high", "low", "current", "chg", "percent", "turnover_rate", "amount", "timestamp"]]
    df[StockTradeDataColumnName.DATE_INDEX.value] = df["timestamp"].apply(
        lambda x: datetime.datetime.utcfromtimestamp(x / 1000) + delta8hours)
    df[StockTradeDataColumnName.TRADE_DATE.value] = df[StockTradeDataColumnName.DATE_INDEX.value].apply(
        lambda x: int(x.strftime(DateFormat.YmdHMS.value)))
    df = df.drop("timestamp", axis=1)
    # df.set_index(keys=StockTradeDataColumnName.DATE_INDEX.value, inplace=True)
    df = df.rename(columns={
        "volume": StockTradeDataColumnName.VOL.value,
        "open": StockTradeDataColumnName.OPEN.value,
        "high": StockTradeDataColumnName.HIGH.value,
        "low": StockTradeDataColumnName.LOW.value,
        'current': StockTradeDataColumnName.CLOSE.value,
        "chg": StockTradeDataColumnName.CHANGE.value,
        "percent": StockTradeDataColumnName.PCT_CHG.value,
        'turnover_rate': StockTradeDataColumnName.TURNOVER_RATE.value,
        "amount": StockTradeDataColumnName.AMOUNT.value
    })
    return df


def quoteList() -> pd.DataFrame:
    """
    沪深一览
    :return:
    """
    url:str = config.get('xueqiu', 'quote_list')
    page = 1
    r = pd.DataFrame()
    while(True):
        urlT = url.replace("pagen", str(page))
        try:
            result = utls.fetch(urlT)
        except:
            result = utls.fetch(urlT)
        if not result["data"]:
            break
        df = pd.DataFrame(result["data"]["list"])
        logger.info(f"下载股票列表数据：{df.shape[0]}条")
        df[StockTradeDataColumnName.STOCK_CODE_FULL.value] = df["symbol"].apply(lambda x: f"{x[2:]}.{x[0:2]}")
        df[StockTradeDataColumnName.STOCK_CODE.value] = df["symbol"].apply(lambda x: f"{x[2:]}")
        df = df[[StockTradeDataColumnName.STOCK_CODE_FULL.value, StockTradeDataColumnName.STOCK_CODE.value, StockTradeDataColumnName.NAME.value]]
        if df.empty:
            break
        page = page + 1
        r = pd.concat([r, df], axis=0)
    return r